package tests;

import java.io.*;

import index.ColumnIndexScan;
import iterator.*;

import iterator.CondExpr;

import iterator.FldSpec;

import iterator.RelSpec;

import java.io.*;

import java.util.*;
import java.lang.*;
import heap.*;
import bufmgr.*;
import diskmgr.*;
import global.*;
import chainexception.*;

import columnar.*;

public class QueryTest implements GlobalConst {

	/*
	 * constructor for all parameters - datafilename , coulmnDBname, columnar
	 * filename , numcolumns
	 */
	public String datafilename, cdbname, filename;
	public int numcolumns;
	public TID[] tidArr;
	ColumnarFile _cf;
	int[] colnosg;
	int[] attrtypesg;

	public QueryTest() {
	}

	

	public void runTest1(String cdbname, String Colfilename, String cname,
			String[] targetcolname, String operator, String value,
			String accesstype) throws IOException

	{
		try
		{
			String dbpath = "/tmp/" + cdbname;
	String record;

	int numbuf, targetnum, nocol;
	Scanner sc = new Scanner(System.in);
	SystemDefs sysdef = new SystemDefs(dbpath, 0, 50, "Clock");
		PCounter.initialize();
		this.filename = Colfilename;
		int i = 0, z = 0;
		
		BufferedReader br = new BufferedReader(new FileReader("/tmp/"+Colfilename+".hdr"));

		while ((record = br.readLine()) != null) {
			z++;
		}
		this.numcolumns = z;
		int[] colnos = new int[this.numcolumns];
		int[] attrtypes = new int[this.numcolumns];
		// all colnames, colnumbers and attr by parsing the name.hdr
		String[] colnames = new String[this.numcolumns];
		
		int condn_columnno = -1, condn_attrType = -1;
		String condn_columnname = " ";
		// target column number and attr
		int[] final_colnums = new int[targetcolname.length];
		int[] final_attr = new int[targetcolname.length];
		String[] targetarray = new String[this.numcolumns];
		// read from name.hdr
		BufferedReader br4 = new BufferedReader(new FileReader("/tmp/"+Colfilename+".hdr"));

		while ((record = br4.readLine()) != null) {

			StringTokenizer st4 = new StringTokenizer(record, "\t");

			while (st4.hasMoreTokens()) {
				StringTokenizer st5 = new StringTokenizer(st4.nextToken(), " ");
				String colName = st5.nextToken().trim();
				colnames[i] = colName;
				int colNum = Integer.parseInt(st5.nextToken().trim());
				colnos[i] = colNum;
				int attrType = Integer.parseInt(st5.nextToken().trim());
				attrtypes[i] = attrType;

				if (colName.equals(cname)) {
					condn_columnno = colNum;
					condn_attrType = attrType;
					condn_columnname = colName;

				}

			}

			i++;

		}
		int[] target_colnums= new int[targetcolname.length];
		int[] target_attr= new int[targetcolname.length];
		int ch=0; 
		for (int p=0;p<targetcolname.length;p++)
		{
		  for(int k=0;k<numcolumns;k++)
		  {
			  
		    if(targetcolname[p].equals(colnames[k]))
		    {
		    	target_attr[p]= attrtypes[k];
		    	target_colnums[p]=k+1;
		    	ch++;    	
		    }
		}
		}

		if(ch!=targetcolname.length)
		{
		 System.out.println("invalid Colname"+ch);
		 System.exit(0);
		}
		int[] tar= new int[numcolumns];
		for(int c=0;c<numcolumns;c++)
		{
			if( c < target_colnums.length)
			  if(target_colnums[c] > 0)
		      tar[target_colnums[c]-1]=1;                 
		}	

		// ---------------------------- diff access types cases
		// -----------------------
		// BTree
		if (accesstype.equalsIgnoreCase("BTree")) {
			System.out.println("Btree check");

			// bi.indexTest("cdbname","hpfile","A","BTree");

			CondExpr[] outFilter = new CondExpr[2];
			outFilter[0] = new CondExpr();
			 if(operator.equals("="))
				  outFilter[0].op    = new AttrOperator(AttrOperator.aopEQ);
				  else if(operator.equals("<"))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopLT);
				  else if(operator.equals(">"))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopGT);
				  else if(operator.equals("<>"))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopNE);
				  else if(operator.equals("<="))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopLE);
				  else if(operator.equals(">="))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopGE);
				  else
				  {
					  System.out.println("Invalid Operator");
				      System.exit(0);
				  }

			outFilter[0].next = null;
			outFilter[0].type1 = new AttrType(AttrType.attrSymbol);
			if (condn_attrType == 1)
				outFilter[0].type2 = new AttrType(AttrType.attrInteger);
			else
				outFilter[0].type2 = new AttrType(AttrType.attrString);
			outFilter[0].operand1.symbol = new FldSpec(new RelSpec(
					RelSpec.outer), 1); // col num ?
			// check datatype of attribute against meta data file
			if (condn_attrType == 1)
				outFilter[0].operand2.integer = Integer.parseInt(value); // datavalue
			else
				outFilter[0].operand2.string = value; // datavalue
			outFilter[1] = null;

			AttrType[] Fstypes = new AttrType[this.numcolumns];
			AttrType[] Stypes = new AttrType[1]; // one attribute

			if (condn_attrType == 1)
				Stypes[0] = new AttrType(AttrType.attrInteger);
			else
				Stypes[0] = new AttrType(AttrType.attrString);
			int j = 0;
			for (int cou = 0; cou < this.numcolumns; cou++) {
				if (attrtypes[cou] == 0)
					j++;
			}
			short[] Ssizes = new short[j];
			for (int cou = 0, k = 0; cou < numcolumns; cou++) {
				if (attrtypes[cou] == 0) {
					Fstypes[cou] = new AttrType(AttrType.attrString);
					Ssizes[k] = strlen;
					k++;
				} else
					Fstypes[cou] = new AttrType(AttrType.attrInteger);
			}
			int numfields_input = 1; // no. of fields in input tuple
			int numfields_output = 1; // no. of fields in output - take from
										// target column names
			FldSpec[] Sprojection = new FldSpec[1];
			// find what fields are required and construct corresponding
			// projection
			Sprojection[0] = new FldSpec(new RelSpec(RelSpec.outer), 1); // order
																			// of
			
			ColumnIndexScan ciscan = null;
			String columnarfilename = filename + (condn_columnno - 1);
			String indexfilename = "Btree" + filename + (condn_columnno - 1);
			try {
				ciscan = new ColumnIndexScan(new IndexType(IndexType.B_Index),
						columnarfilename, indexfilename, Stypes, Ssizes,
						numfields_input, numfields_output, Sprojection,
						outFilter, 1, true, attrtypesg);

			} catch (Exception e) {
				System.out.println("In Btree Index Scan" + e);
			}
			Tuple t = new Tuple();
			try {
				while ((t = ciscan.get_next()) != null) {
					System.out.println("got records in BTree Index scan");
					t.printtup(Fstypes,tar);
				}
			} catch (Exception e) {
				System.err.println("" + e);
				e.printStackTrace();
			}

		}
		// FileScan
		else if (accesstype.equalsIgnoreCase("Filescan")) {
			System.out.println("FileScan check");

			CondExpr[] outFilter = new CondExpr[2];
			outFilter[0] = new CondExpr();
			 if(operator.equals("="))
				  outFilter[0].op    = new AttrOperator(AttrOperator.aopEQ);
				  else if(operator.equals("<"))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopLT);
				  else if(operator.equals(">"))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopGT);
				  else if(operator.equals("<>"))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopNE);
				  else if(operator.equals("<="))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopLE);
				  else if(operator.equals(">="))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopGE);
				  else
				  {
					  System.out.println("Invalid Operator");
				      System.exit(0);
				  }

			outFilter[0].next = null;
			outFilter[0].type1 = new AttrType(AttrType.attrSymbol);

			if (condn_attrType == 1)
				outFilter[0].type2 = new AttrType(AttrType.attrInteger);
			else
				outFilter[0].type2 = new AttrType(AttrType.attrString);
			outFilter[0].operand1.symbol = new FldSpec(new RelSpec(
					RelSpec.outer), condn_columnno);
			// check datatype of attribute against meta data file
			if (condn_attrType == 1)
				outFilter[0].operand2.integer = Integer.parseInt(value); // datavalue
			else
				outFilter[0].operand2.string = value; // datavalue

			outFilter[1] = null;

			Tuple t = new Tuple();

			AttrType[] Stypes = new AttrType[1]; // one attribute
			AttrType[] Fstypes = new AttrType[this.numcolumns];

			// if data value is string
			// Stypes[0] = new AttrType (AttrType.attrString);
			// get the type of column from the input file
			// else if data value is int
			if (condn_attrType == 1)
				Stypes[0] = new AttrType(AttrType.attrInteger);
			else
				Stypes[0] = new AttrType(AttrType.attrString);

			// short [] Fssizes = new short[2];
			int j = 0;
			for (int cou = 0; cou < this.numcolumns; cou++) {
				if (attrtypes[cou] == 0)
					j++;
			}
			short[] Ssizes = new short[j];
			for (int cou = 0, k = 0; cou < numcolumns; cou++) {
				if (attrtypes[cou] == 0) {
					Fstypes[cou] = new AttrType(AttrType.attrString);
					Ssizes[k] = strlen;
					k++;
				} else
					Fstypes[cou] = new AttrType(AttrType.attrInteger);
			}

			FldSpec[] Sprojection = new FldSpec[1];
			// find what fields are required and construct corresponding
			// projection
			Sprojection[0] = new FldSpec(new RelSpec(RelSpec.outer), 1); // order
																			// of
																			// fields
																			// //
																			// add
																			// col
																			// no.
			// Sprojection[1] = new FldSpec(new RelSpec(RelSpec.outer), 2); //
			// order of fields
			// Sprojection[2] = new FldSpec(new RelSpec(RelSpec.outer), 3); //
			// order of fields
			// Sprojection[3] = new FldSpec(new RelSpec(RelSpec.outer), 4); //
			// order of fields
			//	  	 
			short numfields_input = 4; // no. of fields in input tuple
			short numfields_output = 1; // no. of fields in output - take from
										// target column names

			FileScan fs = null;
			try {
				String columnarfilename = filename;// / construct the file name
													// based on column no.
				fs = new FileScan(columnarfilename, Fstypes, Ssizes,
						numfields_input, numfields_output, Sprojection,
						outFilter);
			}

			catch (Exception e) {
				System.err.println("" + e);
			}

			try {
				
				while ((t = fs.get_next()) != null) {
					System.out.println("got records in filescan");
					
					t.printtup(Fstypes,tar);
				}
			} catch (Exception e) {
				System.err.println("" + e);
				e.printStackTrace();
			}
		}
		// ColumnFileScan
		else if (accesstype.equalsIgnoreCase("ColumnFilescan")) {
			// //column scan
			System.out.println(" Column File Scan testing");
			// write conditional expression matching the query
			CondExpr[] outFilter = new CondExpr[2];
			outFilter[0] = new CondExpr();
			 if(operator.equals("="))
				  outFilter[0].op    = new AttrOperator(AttrOperator.aopEQ);
				  else if(operator.equals("<"))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopLT);
				  else if(operator.equals(">"))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopGT);
				  else if(operator.equals("<>"))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopNE);
				  else if(operator.equals("<="))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopLE);
				  else if(operator.equals(">="))
					  outFilter[0].op    = new AttrOperator(AttrOperator.aopGE);
				  else
				  {
					  System.out.println("Invalid Operator");
				      System.exit(0);
				  }

			outFilter[0].next = null;
			outFilter[0].type1 = new AttrType(AttrType.attrSymbol);

			if (condn_attrType == 1)
				outFilter[0].type2 = new AttrType(AttrType.attrInteger);
			// //else if string
			else
				outFilter[0].type2 = new AttrType(AttrType.attrString);
			outFilter[0].operand1.symbol = new FldSpec(new RelSpec(
					RelSpec.outer), 1);
			// check datatype of attribute against meta data file
			// if attribute is string
			if (condn_attrType == 1)
				outFilter[0].operand2.integer = Integer.parseInt(value); // datavalue
			else
				outFilter[0].operand2.string = value; // datavalue

			outFilter[1] = null;

			Tuple t = new Tuple();

			AttrType[] Stypes = new AttrType[1]; // one attribute
			AttrType[] Fstypes = new AttrType[this.numcolumns];

			if (condn_attrType == 1)
				Stypes[0] = new AttrType(AttrType.attrInteger);
			else
				Stypes[0] = new AttrType(AttrType.attrString);

			short[] Ssizes = new short[1];

			for (int cou = 0; cou < numcolumns; cou++) {
				if (attrtypes[cou] == 0) {
					Fstypes[cou] = new AttrType(AttrType.attrString);
					Ssizes[0] = strlen;
				} else
					Fstypes[cou] = new AttrType(AttrType.attrInteger);
			}

			FldSpec[] Sprojection = new FldSpec[1];
			// find what fields are required and construct corresponding
			// projection
			Sprojection[0] = new FldSpec(new RelSpec(RelSpec.outer), 1); // order
																			// of
																			// fields

			short numfields_input = 1; // no. of fields in input tuple
			short numfields_output = 1; // no. of fields in output - take from
										// target column names

			ColumnarFileScan cfs = null;
			try {
				String columnarfilename_attribute = filename
						+ (condn_columnno - 1);// / construct the file name
												// based on column no.
				cfs = new ColumnarFileScan(columnarfilename_attribute, Stypes,
						Ssizes, numfields_input, numfields_output, Sprojection,
						outFilter, attrtypesg);
			}

			catch (Exception e) {
				System.err.println("" + e);
			}
			try {
				 
				while ((t = cfs.get_next()) != null) {
                 t.printtup(Fstypes,tar);
				}
			} catch (Exception e) {
				System.err.println("" + e);
				e.printStackTrace();
			}
		}
		}
		
		catch (Exception e) {
			System.out.println("Exception before displaying pages"+e);
		}
		
		finally {
			try {
				SystemDefs.JavabaseBM.unpinAllPages();
				SystemDefs.JavabaseBM.flushAllPages();
				System.out.println("number of pages read" + PCounter.rcounter);
				System.out.println("number of pages written"
						+ PCounter.wcounter);
			} catch (Exception e)
			{System.out.println("exception"+e);
			}
		}


	}

	public static void main(String args[]) throws IOException, HFException,
			HFBufMgrException, HFDiskMgrException {
	
		String cdbname = "cdbname";
		QueryTest qu = new QueryTest();
				
		Scanner sc= new Scanner(System.in);
		  System.out.println("Enter the target columns in the format colname1:colname2:..");
		   String  token=sc.next();
		   String delims = "[:]+";
		
		   String[] target = token.split(delims);  
		   //System.out.println("lenght"+target.length);
		   
			   System.out.println("Enter the constraint column name");
		     String col = sc.next();
			   System.out.println("Enter the constraint column value");
			     String value = sc.next();
			     System.out.println("Enter the access type btree/filescan/columnfilescan/");
			     String access = sc.next();
		    qu.runTest1(cdbname,"hpfile", col, target, "=", value, access);

	}
}